#ifndef xpack_docker_queue
#define xpack_docker_queue
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::docker_queue::inc
#include"adapter/multi_push.hpp"
#include"define/base_type.hpp"
#include"docker/private/add.length.hpp"
#include"docker/private/single_linked_node.hpp"
#include"dumb/disable_copy.hpp"
#include"dumb/move.hpp"
#include"gc/self_management.hpp"
#include"macro/xexport.hpp"
#include"macro/xforward.hpp"
#include"macro/xitr_foreach.hpp"
#include"macro/xlikely.hpp"
#include"macro/xmodify.hpp"
#include"macro/xstruct.hpp"
#include"macro/xunlikely.hpp"
#include"meta/has_constructor.hpp"
#include"utils/memory.hpp"
#include"utils/value_holder.hpp"
#pragma pop_macro("xuser")

namespace mixc::docker_queue {
    template<
        bool is_enable_length_v = true,
        inc::memory::is_allocator allocator_t = inc::memory::default_allocator_t
    >
    struct queue_conf{
        template<bool is_enable_lengthx_v = is_enable_length_v>
        using set_is_enable_length = queue_conf<is_enable_lengthx_v, allocator_t>;

        template<inc::memory::is_allocator default_allocatorx_t = allocator_t>
        using set_allocator = queue_conf<is_enable_length_v, default_allocatorx_t>;
    };

    template<class itemx_t, class conf_t = queue_conf<>>
    struct queue;

    #define xqueue_conf_t       queue_conf<is_enable_length_v, default_allocator_t>

    template<
        class itemx_t,
        bool is_enable_length_v,
        inc::memory::is_allocator default_allocator_t
    >
    xstruct(
        xspec(queue, itemx_t, xqueue_conf_t),
        xpubb(inc::add_length<is_enable_length_v>),
        xpubb(inc::multi_push<
            queue<itemx_t, xqueue_conf_t>, itemx_t
        >),
        xpubb(inc::self_management),
        xpubb(inc::disable_copy),
        xprof(m_node, inc::single_linked_node_ptr<itemx_t>)
    )
        #undef  xqueue_conf_t
    public:
        using inc::multi_push<the_t, itemx_t>::push;
        using item_t    = itemx_t;
    private:
        using value_t   = inc::value_holder<item_t>;
        using node_t    = inc::single_linked_node<item_t>;       // 纯节点类型
        using nodep     = node_t *;

        template<class guide>
        bool routing(){
            // TODO:==================================================
            throw;
        }

    public:
        // 取消 value_holder 返回值，比较麻烦
        xprops()
            xpubget_pubsetx(head, item_t &){
                xr{
                    auto cur = xthe.m_node.top();
                    return cur ? cur->next[0] : *cur/*nullref，允许外部判空而非直接段错误*/;
                }

                xw{
                    auto cur = xthe.m_node.top();
                    (item_t &)cur->next[0] = xforward(value); // node 是一个链表 + 元素的混合体，具有 item_t & 转换重载
                }
                
                xprops_operator_plus(*xthe.m_node.top()->next, item_t)
            };

            xpubget_pubsetx(tail, item_t &){
                xr{
                    auto & cur = *xthe.m_node.top();
                    return cur;
                }

                xw{
                    auto & cur = *xthe.m_node.top();
                    (item_t &)cur = xforward(value);
                }

                xprops_operator_plus(*xthe.m_node.top(), item_t)
            };

            xpubgetx(is_empty, bool){
                xr{ return xthe.m_node.top() == nullptr; }
            };
        $

        xprops_operator()

    public:
        constexpr queue() : 
            inc::add_length<is_enable_length_v>{},
            inc::multi_push<the_t, itemx_t>{},
            m_node(){
        }

        ~queue() {
            this->clear();
        }

        void clear() {
            nodep cur = nullptr;
            nodep tmp;
            nodep top;

            top = m_node.swap_top(nullptr);

            if constexpr (is_enable_length_v){
                xthe->length    = 0;
            }

            xunlikely(top == nullptr) {
                return;
            }
            else{
                tmp = top;
            }

            do {
                cur = tmp;
                tmp = tmp->next;
                default_allocator_t::template free_with_destroy<node_t>(cur);
            } while (top != tmp);
        }

        template<class forward_item_t>
        requires(inc::has_constructor<item_t, void(forward_item_t &&)>)
        void push(forward_item_t && value) {
            auto new_top            = default_allocator_t::template alloc<node_t>();
            xnew(new_top) node_t(xforward(value));
            this->push_core(new_top);
        }

    private:
        void push_core(nodep new_top){
            // old_top 表示队列最后一个元素，它的下一个元素指向队列第一个元素
            xlikely(auto top = m_node.top(); top != nullptr){
                auto next           = top->next;
                new_top->next       = next;
                top->next           = new_top;
                m_node.swap_top(new_top);
            }
            else{
                new_top->next = new_top;
                m_node.swap_top(new_top);
            }

            if constexpr (is_enable_length_v){
                xthe->length        = xthe->length + 1;
            }
        }

    public:
        value_t pop() {
            auto r                  = value_t{};
            auto head               = nodep{};
            auto top                = m_node.top(); 

            xunlikely(top == nullptr){
                return r;
            }

            if (head = top->next; head == top){
                m_node.swap_top(nullptr);
            }
            else{
                top->next           = head->next;
            }

            if constexpr (is_enable_length_v){
                xthe->length        = xthe->length - 1;
            }

            if (head != nullptr){
                r.hold(inc::move(*head));
                default_allocator_t::template free_with_destroy<node_t>(head);
            }
            return r;
        }

        // 迭代器区
    private:
        template<auto mode_v, class iterator_t>
        void foreach_template(iterator_t const & invoke) const {
            nodep  top      = m_node.top();
            nodep  cur      = top;
            uxx    index    = 0;

            xunlikely(top == nullptr){
                return;
            }

            do{
                cur         = cur->next;
            }while(inc::itr_switch<mode_v>(xmodify(index), invoke, *cur) != loop_t::finish and cur != top);
        }
    public:
        xitr_foreach(item_t)
    $
}
namespace mixc::docker_queue::origin{
    using mixc::docker_queue::queue_conf;
    using mixc::docker_queue::queue;
}

#endif

xexport_space(mixc::docker_queue::origin)
